﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using uk.ac.soton.ses.DAL;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web;

namespace uk.ac.soton.ses.ExperimentCollectionsWebPart
{
    public partial class ExperimentCollectionsWebPartUserControl : UserControl
    {
        private MaterialsMetadataContext _dbcontext = null;

        private int _experimentID = -999;
        public int ExperimentID { get { return this._experimentID; } set { this._experimentID = value; } }

        //Page setup

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            this._dbcontext = HttpContext.Current.GetMaterialsDBContext();

            this.ExperimentCollectionsGridView.RowDataBound += new GridViewRowEventHandler(ExperimentCollectionsGridView_RowDataBound);
            this.ExperimentCollectionsGridView.RowEditing += new GridViewEditEventHandler(ExperimentCollectionsGridView_RowEditing);
            this.ExperimentCollectionsGridView.RowDeleting += new GridViewDeleteEventHandler(ExperimentCollectionsGridView_RowDeleting);
            this.ExperimentCollectionsGridView.RowCancelingEdit += new GridViewCancelEditEventHandler(ExperimentCollectionsGridView_RowCancelingEdit);
            this.ExperimentCollectionsGridView.RowUpdating += new GridViewUpdateEventHandler(ExperimentCollectionsGridView_RowUpdating);

            this.btn_LinkToExistingCollection.Click += new EventHandler(btn_LinkToExistingCollection_Click);
            this.btn_CreateNewCollection.Click += new EventHandler(btn_CreateNewCollection_Click);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (this._experimentID < 0)
            {
                HDCSharedWebFunctions.AddErrorLabel("Experiment ID not set", this.PlaceHolder_Messages);
            }
            else
            {
                //Because we are using viewstate for our control, we only need to databind on first load
                if (!Page.IsPostBack)
                {
                    this.DataBindExperimentCollection();
                }
            }
            //else
            //{
            //    //We need to load the _experimentIDFilter from ViewState which was saved when DataBindToExperiment() was first called
            //    if (this._experimentIDFilter < 0)
            //    {
            //        this._experimentIDFilter = this.GetExperimentIDFromViewState();
            //    }
            //}
        }


        //Control events

        void ExperimentCollectionsGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
        {
            //Get the controls we need to process the update
            GridView gv = (GridView)sender;
            GridViewRow gvr = gv.Rows[gv.EditIndex];

            //Get the updated values using ExtractValuesFromCell (which is not done for us)
            foreach (DataControlFieldCell cell in gvr.Cells)
            {
                cell.ContainingField.ExtractValuesFromCell(e.NewValues, cell, DataControlRowState.Edit, true);
            }

            //Find out which collection was updated
            int collectionID = (int)gv.DataKeys[gv.EditIndex]["ID"];

            //Get the Description
            string newName = (string)(e.NewValues["Name"] ?? "");
            string newDescription = (string)(e.NewValues["Description"] ?? "");

            //Update the collection
            this._dbcontext.UpdateExperimentCollection(collectionID, newName, newDescription, true);

            //Turn off editing
            gv.EditIndex = -1;

            //Rebind the GridView
            this.DataBindExperimentCollection();
        }

        void ExperimentCollectionsGridView_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
        {
            //Get the GridView (using sender or by variable name, doesn't matter)
            GridView gv = (GridView)sender;

            //Turn off editing
            gv.EditIndex = -1;

            //Rebind the GridView
            this.DataBindExperimentCollection();
        }

        void ExperimentCollectionsGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
        {
            //Get the GridView (using sender or by variable name, doesn't matter)
            GridView gv = (GridView)sender;

            //Get a connection to the database
            MaterialsMetadataContext context = HttpContext.Current.GetMaterialsDBContext();

            //Find out which collection is being deleted
            int collectionID = (int)gv.DataKeys[e.RowIndex]["ID"];

            this._dbcontext.DeleteExperimentFromCollection(collectionID, this._experimentID, true);

            //Rebind the GridView
            this.DataBindExperimentCollection();
        }

        void btn_CreateNewCollection_Click(object sender, EventArgs e)
        {
            //Get a connection to the database
            MaterialsMetadataContext context = HttpContext.Current.GetMaterialsDBContext();

            //Find the Experiment record that is being viewed
            Experiment experiment = context.GetExperimentByID(this._experimentID);
            //Experiment experiment = context.Experiments.FirstOrDefault(exp => exp.ID == this._experimentIDFilter);

            ExperimentCollection newExperimentCollection = this._dbcontext.CreateExperimentCollection(true);

            if (newExperimentCollection != null)
            {
                //Set up the a new map, joining the current experiment to the collection
                this._dbcontext.AddExperimentToCollection(newExperimentCollection.ID, this._experimentID, true);
            }

            ////Create a new map to so we can join the current Experiment to the collection
            //ExperimentCollectionExperimentMap newExperimentCollectionMap = new ExperimentCollectionExperimentMap();

            ////Check we have the expected data items
            //if (experiment != null && newExperimentCollection != null && newExperimentCollectionMap != null)
            //{

            //    //Set up the a new map, joining the current experiment to the collection
            //    newExperimentCollectionMap.ExperimentCollection = newExperimentCollection;
            //    newExperimentCollectionMap.Experiment = experiment;

            //    //Add the new experiment map to the database
            //    context.AddToExperimentCollectionExperimentMaps(newExperimentCollectionMap);
            //    context.SaveChanges();
            //}

            //Set the row that was just added to be editable
            this.ExperimentCollectionsGridView.EditIndex = this.ExperimentCollectionsGridView.Rows.Count;

            //Rebind the GridView
            this.DataBindExperimentCollection();
        }

        void btn_LinkToExistingCollection_Click(object sender, EventArgs e)
        {
            string collectionIDString = this.list_CollectionsNotMapped.SelectedValue;
            int collectionID = 0;
            if (int.TryParse(collectionIDString, out collectionID))
            {
                this._dbcontext.AddExperimentToCollection(collectionID, this._experimentID, true);
            }
            this.DataBindExperimentCollection();
        }



        void ExperimentCollectionsGridView_RowEditing(object sender, GridViewEditEventArgs e)
        {
            this.ExperimentCollectionsGridView.EditIndex = e.NewEditIndex;
            this.DataBindExperimentCollection();
        }


        /// <summary>
        /// Retrieves the experiment ID from view state
        /// </summary>
        /// <returns>The ID of the experiment or -1 if the experiment ID has not been saved</returns>
        //private int GetExperimentIDFromViewState()
        //{
        //    int newID = -1;
        //    object viewStateObject = this.ViewState["ExperimentID"];

        //    //Check that the ViewState object exists and is an integer
        //    if (viewStateObject != null && viewStateObject is int)
        //    {
        //        newID = (int)viewStateObject;
        //    }
        //    else
        //    {
        //        newID = -1;
        //    }
        //    return newID;
        //}
        /// <summary>
        /// To provide a way of retrieving the experiment ID at a later date, if we haven't been passed it
        /// </summary>
        /// <param name="newID">The ID to save to view state</param>
        //private void SaveExperimentIDToViewState(int newID)
        //{
        //    this.ViewState["ExperimentID"] = newID;
        //}
        //public void BindToExperiment(int experimentID)
        //{
        //    this._experimentIDFilter = experimentID;
        //    this.SaveExperimentIDToViewState(this._experimentIDFilter);
        //    this.DataBindExperimentCollection();
        //}
        private void DataBindExperimentCollection()
        {
            //if (this._experimentIDFilter < 0)
            //{
            //    this._experimentIDFilter = this.GetExperimentIDFromViewState();
            //}
            if (this._experimentID > 0)
            {
                MaterialsMetadataContext context = HttpContext.Current.GetMaterialsDBContext();
                //Bind experiment collection
                IQueryable<ExperimentCollection> experimentCollection = context.ExperimentCollectionExperimentMaps.Where(map => map.ExperimentID == this._experimentID).Select(map => map.ExperimentCollection);
                this.ExperimentCollectionsGridView.DataSource = experimentCollection.ToList();
                this.ExperimentCollectionsGridView.DataBind();

                //Bind drop down list
                IQueryable<ExperimentCollection> collectionsNotMapped =
                    context.ExperimentCollections
                    .Where(coll =>
                        context.ExperimentCollectionExperimentMaps
                        .Count(map => map.ExperimentID == this._experimentID && map.ExperimentCollectionID == coll.ID) == 0);
                list_CollectionsNotMapped.DataSource = collectionsNotMapped;
                list_CollectionsNotMapped.DataBind();
            }
        }

        void ExperimentCollectionsGridView_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            SPGridView gv = sender as SPGridView;
            SPGridViewRow gvr = e.Row as SPGridViewRow;

            if (gvr == null)
            {
                return;
            }

            ExperimentCollection collection = gvr.DataItem as ExperimentCollection;
            if (collection == null)
            {
                return;
            }

            HyperLink collectionLink = gvr.FindControl("link_CollectionDetails") as HyperLink;
            if (collectionLink != null && collection!=null)
            {
                collectionLink.NavigateUrl = HDCConfiguration.GetUrl_CollectionDetails(collection.ID);
            }
        }
    }
}
